#include "reseau.hpp"

#include <QMessageBox>
#include <QDebug>

Reseau::Reseau(Lobby * lobby, MainWindow * mainWindow, QObject * parent) :
        QObject(parent),
        _mainWindow(mainWindow),
        _lobby(lobby)
{
    _server = new QTcpServer();
}

Reseau::~Reseau()
{
}

bool Reseau::clientExists(const QString & name) const
{
    for (int i = 0; i < _clients.size(); ++i)
        if (name == _clients[i]->name())
            return true;

    return false;
}

void Reseau::connect(int port)
{
    if (!_server->listen(QHostAddress::Any, port))
        emit impossibleToBoundPort(port);
    else
    {
        QObject::connect(_server, SIGNAL(newConnection()), this, SLOT(nouvelleConnexion()));
        emit serverBound();
    }
}

void Reseau::nouvelleConnexion()
{
    QTcpSocket * nouvelleSocket = _server->nextPendingConnection();

    Client * client = new Client(nouvelleSocket, this);

    QObject::connect(client, SIGNAL(deconnexion(QString)), this, SLOT(finConnexion(QString)));
    QObject::connect(client, SIGNAL(identified(QString)), _lobby, SLOT(addClient(QString)));
    QObject::connect(client, SIGNAL(identified(QString)), this, SLOT(nouvelleIdentification(QString)));
    QObject::connect(client, SIGNAL(NTlobbySay(QString)), this, SLOT(nouveauMessage(QString)));
    QObject::connect(client, SIGNAL(NTcreateGame(quint8,qreal)), _mainWindow, SLOT(reactCreateGame(quint8,qreal)));
    QObject::connect(client, SIGNAL(NTgameDestroy(quint8)), _mainWindow, SLOT(reactGameDestroy(quint8)));
    QObject::connect(client, SIGNAL(NTwantToPlay(quint8)), _mainWindow, SLOT(reactWantToPlay(quint8)));
    QObject::connect(client, SIGNAL(NTwantToSee(quint8)), _mainWindow, SLOT(reactWantToSee(quint8)));
    QObject::connect(client, SIGNAL(NTgameQuit(quint8)), _mainWindow, SLOT(reactGameQuit(quint8)));
    QObject::connect(client, SIGNAL(NTdontWantToSeeAnymore(quint8)), _mainWindow, SLOT(reactDontWantToSeeAnymore(quint8)));
    QObject::connect(client, SIGNAL(NTgameSay(quint8,QString)), _mainWindow, SLOT(reactGameSay(quint8,QString)));
    QObject::connect(client, SIGNAL(NTplayMove(quint8,quint8,quint8)), _mainWindow, SLOT(reactPlayMove(quint8,quint8,quint8)));
    QObject::connect(client, SIGNAL(NTskipTurn(quint8)), _mainWindow, SLOT(reactSkipTurn(quint8)));
    QObject::connect(client, SIGNAL(NTdeadGroup(quint8,quint8,quint8)), _mainWindow, SLOT(reactDeadGroup(quint8,quint8,quint8)));
    QObject::connect(client, SIGNAL(NTaliveGroup(quint8,quint8,quint8)), _mainWindow, SLOT(reactAliveGroup(quint8,quint8,quint8)));
    QObject::connect(client, SIGNAL(NTtoPlay(quint8)), _mainWindow, SLOT(reactToPlay(quint8)));
    QObject::connect(client, SIGNAL(NTvalidateGroups(quint8)), _mainWindow, SLOT(reactValidateGroups(quint8)));

    _clients.append(client);

    qWarning() << "New connection from " << nouvelleSocket->peerAddress().toString();
}

void Reseau::finConnexion(const QString & name)
{
    if (!name.isEmpty())
        _lobby->removeClient(name);

    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    _clients.removeOne(client);

    client->deleteLater();

    for (int i = 0; i < _clients.size(); ++i)
        _clients[i]->send(Mid::CLIENTDISCONNECTED, name);
}

void Reseau::sendAll(Mid::MessageID mid, const QString & s0)
{
    for (int i = 0; i < _clients.size(); ++i)
        _clients[i]->send(mid, s0);
}

void Reseau::sendAll(Mid::MessageID mid, quint8 i0)
{
    for (int i = 0; i < _clients.size(); ++i)
        _clients[i]->send(mid, i0);
}

void Reseau::sendAll(Mid::MessageID mid, quint8 i0, const QString & s0)
{
    for (int i = 0; i < _clients.size(); ++i)
        _clients[i]->send(mid, i0, s0);
}

void Reseau::sendAll(Mid::MessageID mid, quint8 i0, quint8 i1, qreal r0, const QString & s0)
{
    for (int i = 0; i < _clients.size(); ++i)
        _clients[i]->send(mid, i0, i1, r0, s0);
}

void Reseau::kick(const QString & name)
{
    for (int i = 0; i < _clients.size(); ++i)
        if (_clients[i]->name() == name)
            _clients[i]->disconnect();
}

QList<Client *> Reseau::clientList() const
{
    return _clients;
}

void Reseau::nouvelleIdentification(const QString & name)
{
    for (int i = 0; i < _clients.size(); ++i)
    {
        if (_clients[i]->name() == name)
        {
            _clients[i]->send(Mid::CLIENTLIST, _lobby->nameList());
            _clients[i]->send(Mid::GAMELIST, _mainWindow->gameList());
        }
        else
            _clients[i]->send(Mid::CLIENTCONNECTED, name);
    }
}

void Reseau::nouveauMessage(const QString & message)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (client->isConnected())
    {
        QString msg = client->name() + " : " + message;
        _lobby->addMessage(msg);

        for (int i = 0; i < _clients.size(); ++i)
            if (_clients[i] != client)
                _clients[i]->send(Mid::LOBBYSAID, msg);
    }
}
